import 'dart:async';

import 'package:bike_ride/api/common_repository.dart';
import 'package:bike_ride/common/mvvm/base_view_model.dart';
import 'package:bike_ride/common/store/unpay.dart';
import 'package:bike_ride/common/util/account_manager.dart';
import 'package:bike_ride/common/util/debouncer.dart';
import 'package:bike_ride/common/util/event_bus_utils.dart';
import 'package:bike_ride/common/util/map_navigator.dart';
import 'package:bike_ride/model/main/model/cmall_card_m.dart';
import 'package:bike_ride/model/main/model/pmt_m.dart';
import 'package:bike_ride/model/main/model/user_info_m.dart';
import 'package:bike_ride/model/main/view/main_v.dart';
import 'package:bike_ride/model/scan/model/scan_m.dart';
import 'package:bike_ride/model/version/version.dart';
import 'package:bike_ride/res/global/globals.dart';
import 'package:bike_ride/res/style/color_styles.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class AppMainPageViewModel extends PageViewModel<AppMainPageState> {
  CancelToken? cancelToken;
  /// 地图marker图片大小
  /// 注意：图片大小devicePixelRatio越大，图片越小
  ImageConfiguration devicePixelRatio =
      const ImageConfiguration(devicePixelRatio: 2);
  double mapZoom = 18;
  // 地图控制器
  final Completer<GoogleMapController> mapController =
      Completer<GoogleMapController>();

  bool isRequestingVehicle = false;
  bool isShowInfoWindow = false;

  // 地图标记、路线规划
  Set<Marker> markers = {};
  Set<Marker> stationMarkers = {};
  Set<Polygon> stationPolygons = {};
  Set<Polygon> areaPolygons = {};
  Set<Polyline> polyLines = {};

  //0:还车站点 1：禁停区，2：禁行区，3：扣车区,4：接客站点
  late BitmapDescriptor normalStationIcon;
  late BitmapDescriptor forbidStationIcon;
  late BitmapDescriptor noWaitStationIcon;
  late BitmapDescriptor lockStationIcon;

  late double lat;
  late double lng;

  ///当前显示的车辆或站点弹窗数据
  dynamic infoModel;
  String? infoWindowTitle;
  String? infoId;

  final unPayStore = UnPay();
  final versionStore = Version();

  bool get isShowTips => unPayStore.unPayOrderList.isNotEmpty || unPayStore.violationList.isNotEmpty;

  /// 动态设置地图marker的InfoWindow
  InfoWindow getVehicleMarkerInfoWindow(String markId){
    if(infoModel != null && infoId == markId){
      return InfoWindow(title: infoWindowTitle,onTap: (){
        MapNavigatorUtil.showMapModalPopup(
            state.context, infoModel.lng, infoModel.lat);
      });
    }
    return InfoWindow.noText;
  }

  hiddenInfoWindow() {
    isShowInfoWindow = false;
    infoModel = null;
    infoWindowTitle = null;
    infoId = null;
    state.notifyChange();
  }

  @override
  onCreate() {
    cancelToken = CancelToken();

    lat = AccountManager.userLatitude!;
    lng = AccountManager.userLongitude!;
    initBitmap();
    getBrandInfo();

    if(AccountManager.isLogin){
      getPmtData();
      getCmallCards();
      getBrandAreaInfo();

      getUserInfo();
      unPayStore.getUnPayOrder().then((_){
        state.notifyChange();
      });
    }

    EventBusUtils.listen(ViolationUnPay(), (_) {
      if(AccountManager.isLogin){
        unPayStore.getUnPayOrder();
      }
    });

    versionStore.latest(state.context);
  }

  @override
  void onDispose() {
    if (!(cancelToken?.isCancelled ?? true)) {
      cancelToken?.cancel();
    }
    // 释放资源
    mapController.future.then((value) {
      value.dispose();
    });
  }

  Future initBitmap() async {
    BitmapDescriptor.fromAssetImage(
            devicePixelRatio, 'assets/images/stop_icon1.png',
            mipmaps: false)
        .then((value) {
      normalStationIcon = value;
    });
    BitmapDescriptor.fromAssetImage(
            devicePixelRatio, 'assets/images/stop_icon2.png',
            mipmaps: false)
        .then((value) {
      forbidStationIcon = value;
      lockStationIcon = value;
    });
    BitmapDescriptor.fromAssetImage(
            devicePixelRatio, 'assets/images/stop_icon11.png',
            mipmaps: false)
        .then((value) {
      noWaitStationIcon = value;
    });
  }

  Future getBrandInfo() async {
    final result = await CommonRepository.getBrandInfoIdl();
    if (result != null) {
      AccountManager.brandInfo = result;
    }
  }

  Future getBrandAreaInfo() async {
    final result =
        await CommonRepository.getBrandAreaInfoIdl(cancelToken: cancelToken);
    if (result != null) {
      AccountManager.areaInfoM = result;
      final mAreaPolygon = Polygon(
          polygonId: PolygonId('${result.brandCode}_${result.areaCode}'),
          fillColor: ColorStyles.color_1E88E5.withOpacity(0.2),
          points: result.operateAreaPoints,
          strokeWidth: 3,
          strokeColor: ColorStyles.color_1E88E5.withOpacity(0.8));
      areaPolygons = {mAreaPolygon};
    }
    state.notifyChange();
  }

  Future<List<PmtM>> getPmtData({String? position}) async {
    return CommonRepository.getPmtDataIdl(cancelToken: cancelToken, position: position);
  }

  Future<CmallCardM?> getCmallCards({int page = 1}) async {
    return CommonRepository.getCmallCardsIdl(page: page);
  }

  Future getNearbyBike({required num lat, required num lng}) async {
    if (isRequestingVehicle) {
      return;
    }
    isRequestingVehicle = true;
    final result = await CommonRepository
        .getNearbyBikeIdl(cancelToken: cancelToken, lat: lat, lng: lng);
    final icon = await BitmapDescriptor.fromAssetImage(
        devicePixelRatio, 'assets/common_v2/ic_map_bike.png',
        mipmaps: false);
    final mMarkers = result
        .map((e) => Marker(
            markerId: MarkerId(e.vid!),
            icon: icon,
            position: LatLng(e.lat!.toDouble(), e.lng!.toDouble()),
            infoWindow: getVehicleMarkerInfoWindow(e.vid!),
            onTap: ()=>state.onVehicleOrStationMarkerTap(e)
    ))
        .toList();
    markers = mMarkers.toSet();
    state.notifyChange();
    isRequestingVehicle = false;
  }

  /// 请求所有类型的站点
  /// [type] 站点类型 1，2，3
  void getAllNearbyPark({required num lat, required num lng, List<int> type = const [1,2,3]})async{
    SingleCall.call(() {
      for(var item in type) {
        getNearbyPark(lat: lat,lng: lng,type:item,reset: type.first == item);
      }
    });
  }

  /// [reset] 是否重置站点数据
  /// [type] 站点类型
  Future getNearbyPark({required num lat, required num lng,required int type,required bool reset}) async {
    if(reset){
      stationMarkers = {};
      stationPolygons = {};
    }
    final result = await CommonRepository.getNearbyParkIdl(cancelToken: cancelToken, lat: lat, lng: lng,type: type,isShowEmptyTip:type == 1);
    final Set<Polygon> mStationPolygon = {};
    final mMarkers = result.map((e) {
      if (e.polygonPoints != null && e.polygonPoints!.isNotEmpty) {
        mStationPolygon.add(Polygon(
          polygonId: PolygonId(e.id!),
          fillColor: Globals.stationFillColorMap[e.groupType!]!,
          points: e.polygonPoints!.first,
          strokeWidth: 2,
          strokeColor: Globals.stationStrokeColorMap[e.groupType!]!,
        ));
      }
      if (e.groupType == 1 || e.groupType == 3 || e.groupType == 4) {
        return Marker(
          markerId: MarkerId(e.id!),
          icon: forbidStationIcon,
          position: LatLng(e.lat!.toDouble(), e.lng!.toDouble()),
          infoWindow: getVehicleMarkerInfoWindow(e.areaId!),
          onTap: ()=>state.onVehicleOrStationMarkerTap(e)
        );
      } else if (e.groupType == 2) {
        return Marker(
          markerId: MarkerId(e.id!),
          icon: noWaitStationIcon,
          position: LatLng(e.lat!.toDouble(), e.lng!.toDouble()),
          infoWindow: getVehicleMarkerInfoWindow(e.areaId!),
          onTap: ()=>state.onVehicleOrStationMarkerTap(e)
        );
      } else {
        return Marker(
          markerId: MarkerId(e.id!),
          icon: normalStationIcon,
          position: LatLng(e.lat!.toDouble(), e.lng!.toDouble()),
          infoWindow: getVehicleMarkerInfoWindow(e.areaId!),
          onTap: ()=>state.onVehicleOrStationMarkerTap(e)
        );
      }
    });
    stationMarkers.addAll(mMarkers.toSet());
    stationPolygons.addAll(mStationPolygon);

    state.notifyChange();
  }


  Future<UserInfoM?> getUserInfo() async {
    final result = await CommonRepository.getUserInfoIdl(
        cancelToken: cancelToken);
    if (result != null) {
      AccountManager.userInfo = result;
    }
    return result;
  }

  @override
  Future<PageViewModel?> requestData({Map<String, dynamic>? params}) {
    return Future.value(null);
  }
}
